package infra

import (
	"encoding/json"
	"fmt"
	"manager/utils"
	"math"
)

const R = 6367000

var Lbs = &lbs{}

type GeoInfo struct {
	Country       string `json:"country"`        // 国家
	Province      string `json:"province"`       // 省份
	City          string `json:"city"`           // 城市
	District      string `json:"district"`       // 区域
	FormattedAddr string `json:"formatted_addr"` // 格式化后地址
}

// lbs 定位服务
type lbs struct {
}

// Distance
// lonA, latA分别为A点的纬度和经度
// lonB, latB分别为B点的纬度和经度
// 返回的距离单位为米
func (l *lbs) Distance(lngA, latA, lngB, latB float64) (distance float64) {
	c := math.Sin(latA)*math.Sin(latB)*math.Cos(lngA-lngB) + math.Cos(latA)*math.Cos(latB)
	return R * math.Acos(c) * math.Pi / 180
}

func (l *lbs) GeoDistance(lng1 float64, lat1 float64, lng2 float64, lat2 float64, unit ...string) float64 {
	const PI float64 = 3.141592653589793

	radlat1 := float64(PI * lat1 / 180)
	radlat2 := float64(PI * lat2 / 180)

	theta := float64(lng1 - lng2)
	radtheta := float64(PI * theta / 180)

	dist := math.Sin(radlat1)*math.Sin(radlat2) + math.Cos(radlat1)*math.Cos(radlat2)*math.Cos(radtheta)

	if dist > 1 {
		dist = 1
	}

	dist = math.Acos(dist)
	dist = dist * 180 / PI
	dist = dist * 60 * 1.1515

	if len(unit) > 0 {
		if unit[0] == "K" {
			dist = dist * 1.609344
		} else if unit[0] == "N" {
			dist = dist * 0.8684
		}
	}

	return dist * 1000
}

// GetGeoInfo 获取定位位置信息
// lat 纬度
// lng 经度
func (l *lbs) GetGeoInfo(lng, lat float64) (info GeoInfo, err error) {
	url := l.getRegeoUrl(lat, lng)
	rsp, err := utils.DoRequest("GET", url, "", map[string]string{})

	type rec struct {
		Regeocode struct {
			AddressComponent struct {
				Country  string `json:"country"`
				Province string `json:"province"`
				City     string `json:"city"`
				District string `json:"district"` // 区域
			} `json:"addressComponent"`
			FormattedAddress string `json:"formatted_address"`
		} `json:"regeocode"`
	}

	var out rec
	err = json.Unmarshal([]byte(rsp), &out)
	if err != nil {
		return
	}

	info = GeoInfo{
		Province:      out.Regeocode.AddressComponent.Province,
		City:          out.Regeocode.AddressComponent.City,
		District:      out.Regeocode.AddressComponent.District,
		FormattedAddr: out.Regeocode.FormattedAddress,
	}
	return
}

func (l *lbs) getRegeoUrl(lat, lng float64) string {
	return "http://restapi.amap.com/v3/geocode/regeo?location=" + fmt.Sprintf("%v,%v", lng, lat) + "&key=17479d86c0c6a0305024e1142351a0a4"
}
